home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Typography Samples / Glyph Layout ƒ / Glyph Layout.c next >
Encoding:
C/C++ Source or Header  |  1996-06-18  |  16.3 KB  |  470 lines  |  [TEXT/KAHL]

  1. /**\
  2. |**| =====================================================================
  3. |**|
  4. |**|    Glyph Layout.c
  5. |**|
  6. |**|    This file contains the calls that this sample needs to make
  7. |**|    the QuickDraw GX shell work correctly.
  8. |**|
  9. |**|    QuickDraw GX Libraries Used:
  10. |**|    "ColorLibrary.c", "FontLibrary.c", "GraphicsDebugLibrary.c",
  11. |**|    "LayoutLibrary.c", "ShapeLibrary.c", and "TransformLibrary.c".
  12. |**|
  13. |**|    6/96 bob    Updated #includes to support changed GX Library names.
  14. |**|                Updated the copyright date.
  15. |**|
  16. |**|    ©1990 - 1996  Apple Computer, Inc.
  17. |**|    All rights reserved.
  18. |**|
  19. |**| =====================================================================
  20. \**/
  21.  
  22.  
  23. #include "QDGX shell.h"
  24. #include <GXLayout.h>
  25. #include "LayoutLibrary.h"
  26.  
  27.  
  28. /**\
  29. |**| ---------------------------------------------------------------------
  30. |**| PROTOTYPES
  31. |**| ---------------------------------------------------------------------
  32. \**/
  33.  
  34. // funtions required by shell
  35.  
  36. void    DoSetup            (void);
  37. void    DoDraw            (WindowPtr wind, Boolean updating);
  38. OSErr    DoCreateNew        (void);
  39. void    DoDispose        (WindowPtr wind);
  40. void    DoIdle            (WindowPtr wind);
  41. void    DoTeardown        (void);
  42. void    DoClick            (WindowPtr wind, Point p);
  43.  
  44. // private functions
  45.  
  46. OSErr    DoWindowInit        (WindowPtr wind);
  47. void    CreateSampleImage    (WindowPtr wind);
  48.  
  49.  
  50. /**\
  51. |**| ---------------------------------------------------------------------
  52. |**| ENUMS
  53. |**| ---------------------------------------------------------------------
  54. \**/
  55. enum { rWindResource = 128 };
  56.  
  57.  
  58. /**\
  59. |**| ---------------------------------------------------------------------
  60. |**| GLOBALS
  61. |**| ---------------------------------------------------------------------
  62. \**/
  63. // If gDebugging = TRUE, graphics library errors and notices will be posted.  This
  64. // functionality will only work with the "debugging" version of QuickDraw GX.
  65. // If the debugging version is not installed, nothing bad will happen, but these
  66. // functions will not work. 
  67.  
  68. Boolean        gDebugging = true;
  69.  
  70. // Set  "gGiveMeValidation" to TRUE if you want receive run-time validation.
  71.  
  72. Boolean        gGiveMeValidation = true;
  73.  
  74.  
  75. // gGraphicsHeapSize sets the size of the graphics heap created by calling the
  76. // GXNewGraphicsClient routine in main () within QuickDraw GX shell.c.  You can determine
  77. // the amount of graphics heap required by using GraphicsBug.  I'm giving it 600K,
  78. // since we need abunch if we have several windows open.
  79.  
  80. long        gGraphicsHeapSize = 600;
  81.  
  82. // gOurPrintingOverrideUPP is a universal proc pointer for our printing event
  83. // override.  This is so that our override can be native PowerPC code if necessary.
  84.  
  85. GXPrintingEventUPP    gOurPrintingOverrideUPP;
  86.  
  87.  
  88.  
  89. /**\
  90. |**| ---------------------------------------------------------------------
  91. |**| DoSetup()
  92. |**| Here's where we initialize any global variables our application needs.
  93. |**| We have only one at this time -- the universal proc pointer for
  94. |**| our printing override.
  95. |**| ---------------------------------------------------------------------
  96. \**/
  97. void DoSetup (void)
  98. {    // Initialize our printing event override UPP
  99.     gOurPrintingOverrideUPP = NewGXPrintingEventProc(MyPrintingEventOverride);
  100. }
  101.  
  102.  
  103. /**\
  104. |**| ---------------------------------------------------------------------
  105. |**| DoDraw()
  106. |**| Draw the contents of the window.  The first parameter is the window
  107. |**| to draw, and the second parameter is true if we're updating an existing
  108. |**| image.  If that's the case, we don't want to change anything, but
  109. |**| just draw what's already there.
  110. |**| ---------------------------------------------------------------------
  111. \**/
  112. void DoDraw (WindowPtr wind, Boolean updating)
  113. {
  114.      #pragma unused (updating)
  115.      GXDrawShape (GetDocShape(wind));
  116. }
  117.  
  118.  
  119. /**\
  120. |**| ---------------------------------------------------------------------
  121. |**| DoCreateNew()
  122. |**| This routine is called when a window needs to be created.
  123. |**| ---------------------------------------------------------------------
  124. \**/
  125. OSErr DoCreateNew (void)
  126. {
  127.     OSErr        err = noErr;
  128.     WindowPtr    wind;
  129.     
  130. // Get and create our window from the resource fork
  131.  
  132.     wind = GetNewWindow(rWindResource, nil, (WindowPtr)-1L);
  133.  
  134. // Attach a default gxViewPort to it, create and iInitialize our
  135. // private data for it, and add a sample image to its page shape.
  136.  
  137.     if ( wind == NULL )
  138.         return (MemError());
  139.  
  140.     GXIgnoreGraphicsNotice(transform_already_set);
  141.     SetDefaultViewPort(GXNewWindowViewPort(wind));            
  142.     GXPopGraphicsNotice();
  143.     
  144.     err = DoWindowInit(wind);
  145.     if ( err != noErr )
  146.         return err;
  147.     
  148.     CreateSampleImage(wind);
  149.     return err;
  150. }
  151.  
  152.  
  153. /**\
  154. |**| ---------------------------------------------------------------------
  155. |**| DoDispose()
  156. |**| This routine is called when a window needs to be disposed of.
  157. |**| ---------------------------------------------------------------------
  158. \**/
  159. void DoDispose (WindowPtr wind)
  160. {
  161.     TH_Doc    doc;
  162.     
  163. // You should always dispose of your GX graphics objects before tossing your window.
  164. // Why?  It's generally good form and this approach guarantees that everything is
  165. // disposed.  If you had not disposed of everything, the call to DisposeWindow should
  166. // dispose of the objects. If you are running the debugging version of QuickDraw GX
  167. // with notices set, you will receive a notice that you had not disposed of everything.
  168. // You can turn notices on in this file by setting gDebugging = TRUE (above).
  169.     
  170.     if ( wind != NULL )
  171.     {
  172.         doc = (TH_Doc)GetWRefCon(wind);        // Remember, this is where we stored our private data.
  173.         GXDisposeShape(GetDocShape(wind));     // Dispose of this doc's shape.
  174.         GXDisposeJob(GetDocJob(wind));        // Dispose of this doc's print job.
  175.         DisposHandle((Handle) doc);            // Dispose of our private data.
  176.         DisposeWindow(wind);                // Dispose of the window.
  177.     }
  178. }
  179.  
  180.  
  181. /**\
  182. |**| ---------------------------------------------------------------------
  183. |**| DoIdle()
  184. |**| This routine is called to do things while idling through the event loop.
  185. |**| ---------------------------------------------------------------------
  186. \**/
  187. void DoIdle (WindowPtr wind)
  188. {
  189. }
  190.  
  191.  
  192. /**\
  193. |**| ---------------------------------------------------------------------
  194. |**| DoTeardown()
  195. |**| This routine is called just before we quit to remove anything 
  196. |**| persistent that might have been setup by DoSetup().
  197. |**| ---------------------------------------------------------------------
  198. \**/
  199. void DoTeardown (void)
  200. {
  201.     DisposeRoutineDescriptor(gOurPrintingOverrideUPP);
  202. }
  203.  
  204.  
  205. /**\
  206. |**| ---------------------------------------------------------------------
  207. |**| DoClick()
  208. |**| ---------------------------------------------------------------------
  209. \**/
  210. void DoClick(WindowPtr window, Point p)
  211. {
  212. }
  213.  
  214.  
  215.  
  216.  
  217.  
  218. /**\
  219. |**| ---------------------------------------------------------------------
  220. |**| DoWindowInit()
  221. |**| In this function we create and initialize the the private document
  222. |**| structure for a new window.  This structure contains the print job and
  223. |**| the shape which is drawn in the window.  We store this data in a handle
  224. |**| and hang it off the window's refCon field for easy retrieval.  By doing
  225. |**| this, rather than using globals, we can create many windows containing
  226. |**| unique print jobs and shapes.
  227. |**| ---------------------------------------------------------------------
  228. \**/
  229. OSErr DoWindowInit (WindowPtr wind)
  230. {
  231.     OSErr    err = noErr;
  232.     gxJob    docJob;
  233.     gxShape    docPage;
  234.     TH_Doc    windDoc;
  235.  
  236.  
  237. // Create the page shape. We set the unique items attribute to make sure that each item
  238. // added to the picture has a unique reference. If this attribute was not set, we would
  239. // not see all copies of anything we add to the shape multiple times -- we'd just see
  240. // the last version added.        
  241.  
  242.     docPage = GXNewShape(gxPictureType);
  243.     GXSetShapeAttributes(docPage, (GXGetShapeAttributes(docPage) | gxUniqueItemsShape));
  244.     
  245.     
  246. // Create a print job for this document.  This will be the same as the system default until
  247. // the user goes through the dialogs for Page Setup or Print…
  248.  
  249.     err = GXNewJob(&docJob);
  250.     
  251.     
  252. // If there are no errors, create a handle the size of our document structure and store
  253. // the print job and page shape in it.  Store the handle in the window's refCon field so
  254. // that we can get at it.  (Note that the utility routines "GetDocJob" and "GetDocShape"
  255. // can be used to do this easily.
  256.  
  257.     if ( err == noErr )
  258.     {
  259.         windDoc = (TH_Doc) NewHandleClear(sizeof(T_Doc));
  260.  
  261.         if ( windDoc == NULL )
  262.             err = MemError();
  263.         else
  264.         {
  265.             (*windDoc)->docJob = docJob;
  266.             (*windDoc)->docPage = docPage;
  267.             SetWRefCon(wind, (long) windDoc);
  268.         }
  269.  
  270. // Now install our application override for PrintingEvent so that we can
  271. // support the new movable-modal printing dialog boxes.
  272.  
  273.         GXInstallApplicationOverride(docJob, gxPrintingEventMsg, gOurPrintingOverrideUPP);
  274.  
  275.     }
  276.  
  277.     return err;
  278. }
  279.  
  280.  
  281. /**\
  282. |**| ---------------------------------------------------------------------
  283. |**| CreateSampleImage()
  284. |**| This function creates primitive shapes and adds them to the window's page shape.
  285. |**| ---------------------------------------------------------------------
  286. \**/
  287. void CreateSampleImage (WindowPtr wind)
  288. {
  289.     Rect    ourWindowRect = wind->portRect; // the rectangle for this window
  290.                                             // in QuickDraw coordinates
  291.     
  292.     gxRunControls     runControls;        // a default run controls structure
  293.     
  294.     gxShape         layout;                // the layout shape we're creating
  295.     gxShape            glyphs;                // the glyph shape holding glyphs from our layout
  296.     gxShape         thePage;            // this window's page shape
  297.     gxLayoutOptions layoutOptions;        // a default layout options structure
  298.     gxStyle         glyphStyles[3];        // an array of styles to use building our layout
  299.     char *            text1 = "Aetna ";    // text of the first run
  300.  
  301. // The text of the second run is "Arabic Macintosh" in Arabic: */
  302. // meem, alif, kaf,  noon, tah,  wau,  shin, <sp>, alif, lam,  ein,  reh,  beh,  yeh 
  303.  
  304.     static char     text2[] =     {0xE5, 0xC7, 0xE3, 0xE6, 0xCA, 0xE8, 0xD4,
  305.                                  0x20, 0xC7, 0xE4, 0xD9, 0xD1, 0xC8, 0xEA, 0};
  306.  
  307.     char *            text3 = " Office AWAY.";    // the text of the third run
  308.     char *            textRuns[3];        // array to hold the three text runs
  309.     short             textLengths[3];        // array to hold the lengths of each run
  310.     short             totalLength;        // the length of all runs together
  311.     gxPoint         posn;                // position of the layout shape
  312.     gxGlyphcode     layoutGlyphs[35];    // array to hold glyph codes of glyphs from layout
  313.     gxPoint         layoutPositions[35]; // array to hold locations of glyphs from layout
  314.     gxPoint         layoutTangents[35]; // array to hold tangents of glyphs from layout
  315.     long             layoutGlyphCount;    // the count of glyphs in the layout
  316.     long             layoutAdvance[2];    // an array of advance bits for glyphs from layout
  317.     long             layoutRuns;            // the number of style runs found in the layout
  318.     short             layoutRunCounts[3];    // array of number of glyphs in each style run
  319.     short             level0 = 0;            // a variable to hold zero (we need its address)
  320.     gxStyle         layoutStyles[3];    // array to receive styles found in layout shape
  321.  
  322. // Initialize the array of text runs for our layout shape
  323.  
  324.     textRuns[0] = text1;
  325.     textRuns[1] = text2;
  326.     textRuns[2] = text3;
  327.     
  328. // Initialize the text lengths.
  329.  
  330.     textLengths[0] = MyStrLength(text1);
  331.     textLengths[1] = MyStrLength(text2);
  332.     textLengths[2] = MyStrLength(text3);
  333.     
  334.     totalLength = textLengths[0] + textLengths[1] + textLengths[2];
  335.  
  336. // Use library routines to initialize default gxLayoutOptions and gxRunControls structures
  337.  
  338.     InitializeLayoutOptions (&layoutOptions);
  339.     InitializeRunControls (&runControls);
  340.     
  341. // Position the layout almost half way down the left edge of the window. Set 
  342. // the layout's width to the window's width and set the flushness to 1/2, this
  343. // will cause the layout to center in the window.  Note that ourWindowRect is
  344. // not in fixed coordinates, so we have to make it fixed to use it.
  345.  
  346.     layoutOptions.width = ff(ourWindowRect.right - ourWindowRect.left);
  347.     layoutOptions.flush = fract1/2;
  348.  
  349.     posn.x = 0;
  350.     posn.y = ff((ourWindowRect.bottom - ourWindowRect.top) / 2) - ff(25);
  351.     
  352.  
  353. // Use the library routines to initialize three style runs.  The first one is 38-point
  354. // Helvetica.  NewLayoutStyle is found in layout library.c.
  355.  
  356.     glyphStyles[0] = NewLayoutStyle(
  357.         (char *) "\pHelvetica",            // the gxFontName for the style
  358.         ff(38),                            // the point size in fixed point
  359.         0,                                // gxTextAttributes (none)
  360.         &runControls,                    // our default run controls
  361.         nil,                            // run features (none for us)
  362.         0,                                // count of run features
  363.         nil);                            // style run overrides (none for us)
  364.  
  365. // The second one is 38-point Baghdad.
  366.  
  367.     glyphStyles[1] = NewLayoutStyle(
  368.         (char *) "\pBaghdad Plain",        // the gxFontName for the style
  369.         ff(38),                            // the point size in fixed format
  370.         0,                                // gxTextAttributes (none)
  371.         &runControls,                    // our default run controls
  372.         nil,                            // run featuers (none for this style)
  373.         0,                                 // count of run features
  374.         nil);                            // style run overrides (none for us)
  375.     
  376. // The third and final one is 38-point Times Roman
  377.  
  378.     glyphStyles[2] = NewLayoutStyle(
  379.         (char *) "\pTimes Roman",        // the gxFontName for this style
  380.         ff(38),                            // the point size (fixed format)
  381.         0,                                // no gxTextAttributes
  382.         &runControls,                    // our default run controls
  383.         nil,                            // no run features
  384.         0,                                // count of no run features = 0
  385.         nil);                            // style run overrides (still none)
  386.     
  387. // We're ready to build our layout now!
  388.  
  389.     layout = GXNewLayout(
  390.         3,                                    // count of text runs
  391.         textLengths,                        // array of lengths of each run
  392.         (void *)textRuns,                    // array of pointers to the text
  393.         3,                                    // count of style runs
  394.         textLengths,                        // array of the byte lengths of each run
  395.         glyphStyles,                        // array of the styles
  396.         1,                                    // number of levels in the layout
  397.         &totalLength,                        // array of lengths of levels (only one)
  398.         &level0,                            // array of the levels (only one)
  399.         &layoutOptions,                        // options (default)
  400.         &posn);                                // position of the layout shape (none)
  401.         
  402. // Now that we have a layout shape, we show how to get glyphs back from it.
  403. // We can do this several ways.  One easy way is to call GXPrimitiveShape on
  404. // the layout shape, which changes it permanently to a glyph shape.  Of course,
  405. // then you can't change it back to a layout.  A non-destructive way is to call
  406. // GXGetLayoutGlyphs, which gives us back a glyph shape as well as all kinds of
  407. // wonderfully useful information about the layout shape's geometry.
  408.  
  409.     GXIgnoreGraphicsNotice(glyph_tangents_have_no_effect);        // we don't care
  410.     layoutGlyphCount = GXGetLayoutGlyphs(
  411.         layout,                                // the layout to get glyphs from
  412.         layoutGlyphs,                        // an array of glyph codes we're getting
  413.         layoutPositions,                    // the positions of each glyph in the array
  414.         layoutAdvance,                        // the advance bits for all the glyphs
  415.         layoutTangents,                        // the tangents for all the glyphs
  416.         &layoutRuns,                        // the number of style runs in the layout
  417.         layoutRunCounts,                    // the number of glyphs in each style run
  418.         layoutStyles);                        // the styles from the layout shape
  419.     GXPopGraphicsNotice();
  420.     
  421. // Now we're going to make a new glyph shape that reflects all this information.
  422. // After creating a new glyph shape, we set the gxIgnorePlatformShape attribute
  423. // bit on it.  Why?  That tells QuickDraw GX to interpret the "text" we're sending
  424. // to layout not as ASCII or any other platform or script, but instead as actual
  425. // glyph offsets, which is what we got back from GXGetLayoutGlyphs.  Then we're
  426. // ready to stuff our shape full of the glyph information we got.  Remember that
  427. // a single glyph shape can draw multiple glyphs.
  428.  
  429.     glyphs = GXNewShape(gxGlyphType);
  430.     GXSetShapeAttributes(glyphs, GXGetShapeAttributes(glyphs) | gxIgnorePlatformShape);
  431.  
  432.     GXSetGlyphs(
  433.         glyphs,                                // the glyph shape to set
  434.         layoutGlyphCount,                    // the count of glyphs we're setting in
  435.         (unsigned char *) layoutGlyphs,        // the glyph codes (the "text")
  436.         layoutPositions,                    // the positions of each glyph
  437.         layoutAdvance,                        // the advance bits for each glyph
  438.         layoutTangents,                        // the tangents for each glyph
  439.         layoutRunCounts,                    // the number of glyphs in each style run
  440.         layoutStyles);                        // the style runs
  441.  
  442. // Move the new shape down vertically 50 pixels so it doesn't overlap the layout shape.
  443. // Since we're using the same positions we got from the layout shape, failure to move
  444. // the new glyph shape would make them draw right on top of each other.
  445.  
  446.     GXMoveShape(glyphs, 0, ff(50));
  447.  
  448. // Get this window's page shape and add our layout and glyph shapes to it.
  449.  
  450.     thePage = GetDocShape(wind);
  451.     
  452.     AddToShape(thePage, layout);
  453.     AddToShape(thePage, glyphs);
  454.     
  455. // Dispose of all the stuff we created
  456.  
  457.     GXDisposeShape(layout);
  458.     GXDisposeShape(glyphs);
  459.     GXDisposeStyle(glyphStyles[0]);
  460.     GXDisposeStyle(glyphStyles[1]);
  461.     GXDisposeStyle(glyphStyles[2]);
  462.  
  463.  
  464. // Invalidate the window's portRect so that everything gets updated.
  465.     
  466.     SetPort(wind);
  467.     InvalRect(&ourWindowRect);
  468. }
  469.  
  470.